frontend architecture

安装量: 49
排名: #15272

安装

npx skills add https://github.com/exceptionless/exceptionless --skill frontend-architecture
Frontend Architecture
Located in
src/Exceptionless.Web/ClientApp
. The Svelte SPA is the primary client.
Directory Structure
src/
├── lib/
│ ├── features/ # Feature slices (vertical organization)
│ │ ├── auth/
│ │ │ ├── api.svelte.ts
│ │ │ ├── models/
│ │ │ ├── schemas.ts
│ │ │ └── components/
│ │ ├── organizations/
│ │ ├── projects/
│ │ ├── events/
│ │ └── shared/ # Cross-feature shared code
│ ├── components/ # App-wide shared components
│ │ └── ui/ # shadcn-svelte components
│ ├── generated/ # API-generated types
│ └── utils/ # Utility functions
├── routes/
│ ├── (app)/ # Authenticated app routes
│ ├── (auth)/ # Authentication routes
│ └── (public)/ # Public routes
└── app.html
Route Groups
Organize routes by authentication/layout requirements:
routes/
├── (app)/ # Requires authentication
│ ├── +layout.svelte # App layout with nav
│ ├── organizations/
│ └── projects/
├── (auth)/ # Login/signup flows
│ ├── +layout.svelte # Minimal auth layout
│ ├── login/
│ └── signup/
└── (public)/ # Public pages
├── +layout.svelte # Marketing layout
└── pricing/
Feature Slices
Organize by feature, aligned with API controllers:
features/organizations/
├── api.svelte.ts # TanStack Query hooks
├── models/
│ └── index.ts # Re-exports from generated
├── schemas.ts # Zod validation schemas
├── options.ts # Dropdown options, enums
└── components/
├── organization-card.svelte
├── organization-form.svelte
└── dialogs/
└── create-organization-dialog.svelte
API Client Pattern
Centralize API calls per feature:
// features/organizations/api.svelte.ts
import
{
createQuery
,
createMutation
,
useQueryClient
,
}
from
"@tanstack/svelte-query"
;
import
{
useFetchClient
}
from
"@exceptionless/fetchclient"
;
import
type
{
Organization
,
CreateOrganizationRequest
}
from
"./models"
;
export
function
getOrganizationsQuery
(
)
{
const
client
=
useFetchClient
(
)
;
return
createQuery
(
(
)
=>
(
{
queryKey
:
[
"organizations"
]
,
queryFn
:
async
(
)
=>
{
const
response
=
await
client
.
getJSON
<
Organization
[
]
>
(
"/organizations"
)
;
if
(
!
response
.
ok
)
throw
response
.
problem
;
return
response
.
data
!
;
}
,
}
)
)
;
}
export
function
postOrganizationMutation
(
)
{
const
client
=
useFetchClient
(
)
;
const
queryClient
=
useQueryClient
(
)
;
return
createMutation
(
(
)
=>
(
{
mutationFn
:
async
(
data
:
CreateOrganizationRequest
)
=>
{
const
response
=
await
client
.
postJSON
<
Organization
>
(
"/organizations"
,
data
,
)
;
if
(
!
response
.
ok
)
throw
response
.
problem
;
return
response
.
data
!
;
}
,
onSuccess
:
(
)
=>
{
queryClient
.
invalidateQueries
(
{
queryKey
:
[
"organizations"
]
}
)
;
}
,
}
)
)
;
}
Model Re-exports
Re-export generated models through feature model folders:
// features/organizations/models/index.ts
export
type
{
Organization
,
CreateOrganizationRequest
,
UpdateOrganizationRequest
,
}
from
"$lib/generated"
;
// Add feature-specific types
export
interface
OrganizationWithStats
extends
Organization
{
eventCount
:
number
;
projectCount
:
number
;
}
Barrel Exports
Use
index.ts
for clean imports:
// features/organizations/index.ts
export
{
getOrganizationsQuery
,
postOrganizationMutation
}
from
"./api.svelte"
;
export
type
{
Organization
,
CreateOrganizationRequest
}
from
"./models"
;
export
{
organizationSchema
}
from
"./schemas"
;
Shared Components
Place truly shared components in appropriate locations:
lib/
├── features/shared/ # Shared between features
│ ├── components/
│ │ ├── formatters/ # Boolean, date, number formatters
│ │ ├── loading/
│ │ └── error/
│ └── utils/
└── components/ # App-wide components
├── ui/ # shadcn-svelte
├── layout/
└── dialogs/ # Global dialogs
Generated Types
When API contracts change:
npm
run generate-models
Prefer regeneration over hand-writing DTOs. Generated types live in
$lib/generated
.
Import Aliases
// Configured in svelte.config.js
import
{
Button
}
from
"$comp/ui/button"
;
// $lib/components
import
{
User
}
from
"$features/users/models"
;
// $lib/features
import
{
formatDate
}
from
"$shared/formatters"
;
// $lib/features/shared
Composite Component Pattern
Study existing components before creating new ones:
Dialogs
See
/components/dialogs/
Dropdowns
Use
options.ts
with
DropdownItem[]
Forms
Follow TanStack Form patterns in svelte-forms skill
返回排行榜